using System.Text;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using SkiaSharp;

namespace Lzfy_His_Service.Services
{
    public class CaptchaService : ICaptchaService
    {
        private readonly IMemoryCache _cache;
        private readonly ILogger<CaptchaService> _logger;
        private readonly Random _random;
        private const int CaptchaLength = 4;
        private const int CaptchaWidth = 120;
        private const int CaptchaHeight = 40;
        private const int ExpirationMinutes = 5;
        
        // 验证码字符集（排除容易混淆的字符）
        private const string CaptchaChars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
        
        public CaptchaService(IMemoryCache cache, ILogger<CaptchaService> logger)
        {
            _cache = cache;
            _logger = logger;
            _random = new Random();
        }
        
        public async Task<string> GenerateCaptchaAsync(string sessionId)
        {
            try
            {
                // 生成验证码文本
                var captchaText = GenerateRandomText();
                
                // 将验证码存储到缓存中
                var cacheKey = $"captcha_{sessionId}";
                _cache.Set(cacheKey, captchaText.ToUpper(), TimeSpan.FromMinutes(ExpirationMinutes));
                
                // 生成验证码图片
                var imageBase64 = await GenerateCaptchaImageAsync(captchaText);
                
                _logger.LogInformation($"Generated captcha for session {sessionId}");
                return imageBase64;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Error generating captcha for session {sessionId}");
                throw;
            }
        }
        
        public async Task<byte[]> GenerateCaptchaImageBytesAsync(string sessionId)
        {
            try
            {
                // 生成验证码文本
                var captchaText = GenerateRandomText();
                
                // 将验证码存储到缓存中
                var cacheKey = $"captcha_{sessionId}";
                _cache.Set(cacheKey, captchaText.ToUpper(), TimeSpan.FromMinutes(ExpirationMinutes));
                
                // 生成验证码图片字节数组
                var imageBytes = await GenerateCaptchaImageBytesInternalAsync(captchaText);
                
                _logger.LogInformation($"Generated captcha image bytes for session {sessionId}");
                return imageBytes;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Error generating captcha image bytes for session {sessionId}");
                throw;
            }
        }
        
        public Task<bool> ValidateCaptchaAsync(string sessionId, string captcha)
        {
            try
            {
                if (string.IsNullOrEmpty(sessionId) || string.IsNullOrEmpty(captcha))
                {
                    return Task.FromResult(false);
                }
                
                var cacheKey = $"captcha_{sessionId}";
                if (_cache.TryGetValue(cacheKey, out string? storedCaptcha))
                {
                    // 验证成功后立即删除验证码（防止重复使用）
                    _cache.Remove(cacheKey);
                    
                    var isValid = string.Equals(storedCaptcha, captcha.ToUpper(), StringComparison.OrdinalIgnoreCase);
                    _logger.LogInformation($"Captcha validation for session {sessionId}: {(isValid ? "Success" : "Failed")}");
                    return Task.FromResult(isValid);
                }
                
                _logger.LogWarning($"Captcha not found or expired for session {sessionId}");
                return Task.FromResult(false);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Error validating captcha for session {sessionId}");
                return Task.FromResult(false);
            }
        }
        
        public async Task ClearExpiredCaptchasAsync()
        {
            // MemoryCache 会自动清理过期项，这里可以添加额外的清理逻辑
            await Task.CompletedTask;
        }
        
        private string GenerateRandomText()
        {
            var result = new StringBuilder();
            for (int i = 0; i < CaptchaLength; i++)
            {
                result.Append(CaptchaChars[_random.Next(CaptchaChars.Length)]);
            }
            return result.ToString();
        }
        
        private Task<string> GenerateCaptchaImageAsync(string text)
        {
            try
            {
                // 创建图像表面
                using var surface = SKSurface.Create(new SKImageInfo(CaptchaWidth, CaptchaHeight, SKColorType.Rgba8888, SKAlphaType.Premul));
                var canvas = surface.Canvas;

                // 绘制背景
                canvas.Clear(SKColors.White);

                // 绘制干扰线 - 保持安全性
                using var paint = new SKPaint
                {
                    Color = SKColors.LightGray,
                    StrokeWidth = 1,
                    IsAntialias = false // 禁用抗锯齿提高性能
                };

                var random = new Random();
                for (int i = 0; i < 10; i++) // 保持干扰线数量
                {
                    paint.Color = new SKColor(
                        (byte)random.Next(150, 255),
                        (byte)random.Next(150, 255),
                        (byte)random.Next(150, 255));

                    canvas.DrawLine(
                        random.Next(CaptchaWidth),
                        random.Next(CaptchaHeight),
                        random.Next(CaptchaWidth),
                        random.Next(CaptchaHeight),
                        paint);
                }

                // 绘制噪点 - 保持安全性
                for (int i = 0; i < 50; i++) // 保持噪点数量
                {
                    paint.Color = new SKColor(
                        (byte)random.Next(150, 255),
                        (byte)random.Next(150, 255),
                        (byte)random.Next(150, 255));

                    canvas.DrawPoint(
                        random.Next(CaptchaWidth),
                        random.Next(CaptchaHeight),
                        paint);
                }

                // 绘制验证码文本
                var fonts = new[] { "Arial", "Verdana" }; // 保持字体选择

                using var textPaint = new SKPaint
                {
                    Color = new SKColor(
                        (byte)random.Next(50, 150),
                        (byte)random.Next(50, 150),
                        (byte)random.Next(50, 150)),
                    TextSize = 18,
                    IsAntialias = false, // 禁用抗锯齿提高性能
                    Typeface = SKTypeface.FromFamilyName(fonts[random.Next(fonts.Length)], SKFontStyle.Bold)
                };

                // 测量文本宽度并计算起始位置
                var textWidth = textPaint.MeasureText(text);
                var startX = (CaptchaWidth - textWidth) / 2;
                var startY = (CaptchaHeight + textPaint.TextSize) / 2 - 5;

                // 添加文本扭曲效果
                for (int i = 0; i < text.Length; i++)
                {
                    var charX = startX + textPaint.MeasureText(text.Substring(0, i));
                    var offsetY = random.Next(-3, 3); // 保持扭曲幅度
                    var offsetX = random.Next(-1, 1); // 保持扭曲幅度

                    canvas.DrawText(
                        text[i].ToString(),
                        charX + offsetX,
                        startY + offsetY,
                        textPaint);
                }

                // 转换为Base64
                using var image = surface.Snapshot();
                using var data = image.Encode(SKEncodedImageFormat.Png, 80); // 保持图像质量
                var base64 = Convert.ToBase64String(data.ToArray());

                return Task.FromResult($"data:image/png;base64,{base64}");
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "生成验证码图像时发生错误");
                throw;
            }
        }
        
        private async Task<byte[]> GenerateCaptchaImageBytesInternalAsync(string text)
        {
            return await Task.Run(() =>
            {
                using var surface = SKSurface.Create(new SKImageInfo(CaptchaWidth, CaptchaHeight, SKColorType.Rgba8888, SKAlphaType.Premul));
                var canvas = surface.Canvas;
                
                // 设置背景色
                canvas.Clear(SKColors.White);
                
                // 绘制干扰线 - 保持安全性
                using var paint = new SKPaint
                {
                    Color = SKColors.LightGray,
                    StrokeWidth = 1,
                    IsAntialias = false // 禁用抗锯齿提高性能
                };

                var random = new Random();
                for (int i = 0; i < 10; i++) // 保持干扰线数量
                 {
                    paint.Color = new SKColor(
                        (byte)random.Next(150, 255),
                        (byte)random.Next(150, 255),
                        (byte)random.Next(150, 255));

                    canvas.DrawLine(
                        random.Next(CaptchaWidth),
                        random.Next(CaptchaHeight),
                        random.Next(CaptchaWidth),
                        random.Next(CaptchaHeight),
                        paint);
                }

                // 绘制噪点 - 保持安全性
                for (int i = 0; i < 50; i++) // 保持噪点数量
                {
                    paint.Color = new SKColor(
                        (byte)random.Next(150, 255),
                        (byte)random.Next(150, 255),
                        (byte)random.Next(150, 255));

                    canvas.DrawPoint(
                        random.Next(CaptchaWidth),
                        random.Next(CaptchaHeight),
                        paint);
                }

                // 绘制验证码文本
                var fonts = new[] { "Arial", "Verdana" }; // 保持字体选择

                using var textPaint = new SKPaint
                {
                    Color = new SKColor(
                        (byte)random.Next(50, 150),
                        (byte)random.Next(50, 150),
                        (byte)random.Next(50, 150)),
                    TextSize = 18,
                    IsAntialias = false, // 禁用抗锯齿提高性能
                    Typeface = SKTypeface.FromFamilyName(fonts[random.Next(fonts.Length)], SKFontStyle.Bold)
                };

                // 测量文本宽度并计算起始位置
                var textWidth = textPaint.MeasureText(text);
                var startX = (CaptchaWidth - textWidth) / 2;
                var startY = (CaptchaHeight + textPaint.TextSize) / 2 - 5;

                // 添加文本扭曲效果
                for (int i = 0; i < text.Length; i++)
                {
                    var charX = startX + textPaint.MeasureText(text.Substring(0, i));
                    var offsetY = random.Next(-3, 3); // 保持扭曲幅度
                    var offsetX = random.Next(-1, 1); // 保持扭曲幅度

                    canvas.DrawText(
                        text[i].ToString(),
                        charX + offsetX,
                        startY + offsetY,
                        textPaint);
                }
                
                // 转换为字节数组 - 保持图像质量
                using var image = surface.Snapshot();
                using var data = image.Encode(SKEncodedImageFormat.Png, 80); // 保持图像质量
                return data.ToArray();
            });
        }
        
        private void DrawInterferenceLines(SKCanvas canvas)
        {
            using var paint = new SKPaint
            {
                Color = SKColors.LightGray,
                StrokeWidth = 1,
                Style = SKPaintStyle.Stroke
            };
            
            for (int i = 0; i < 5; i++)
            {
                var x1 = _random.Next(CaptchaWidth);
                var y1 = _random.Next(CaptchaHeight);
                var x2 = _random.Next(CaptchaWidth);
                var y2 = _random.Next(CaptchaHeight);
                canvas.DrawLine(x1, y1, x2, y2, paint);
            }
        }
        
        private void DrawCaptchaText(SKCanvas canvas, string text)
        {
            var fonts = new[] { "Arial", "Times New Roman", "Courier New" };
            var colors = new[] { SKColors.Black, SKColors.DarkBlue, SKColors.DarkRed, SKColors.DarkGreen };
            
            for (int i = 0; i < text.Length; i++)
            {
                var fontFamily = fonts[_random.Next(fonts.Length)];
                var fontSize = _random.Next(16, 20);
                var color = colors[_random.Next(colors.Length)];
                
                using var paint = new SKPaint
                {
                    Color = color,
                    TextSize = fontSize,
                    IsAntialias = true,
                    Typeface = SKTypeface.FromFamilyName(fontFamily, SKFontStyle.Bold)
                };
                
                var x = 10 + i * 25 + _random.Next(-3, 3);
                var y = 25 + _random.Next(-3, 3);
                
                // 随机旋转角度
                var angle = _random.Next(-15, 15);
                canvas.Save();
                canvas.RotateDegrees(angle, x, y);
                canvas.DrawText(text[i].ToString(), x, y, paint);
                canvas.Restore();
            }
        }
        
        private void AddNoise(SKCanvas canvas)
        {
            using var paint = new SKPaint
            {
                Color = SKColors.LightGray,
                Style = SKPaintStyle.Fill
            };
            
            for (int i = 0; i < 50; i++)
            {
                var x = _random.Next(CaptchaWidth);
                var y = _random.Next(CaptchaHeight);
                canvas.DrawCircle(x, y, 1, paint);
            }
        }
    }
}